import axiosInstance from '@/api/axios'
import {
  ContentTypeEnum,
  RequestBodyEnum,
  RequestContentTypeEnum,
  RequestDataTypeEnum,
  RequestHttpEnum,
  RequestParamsObjType,
  RequestParamsTypeEnum
} from '@/enums/httpEnum'
import { RequestConfigType, RequestGlobalConfigType } from '@/store/modules/chartEditStore/chartEditStore'

export const get = <T = any>(url: string, params?: object) => {
  return axiosInstance<T>({
    url,
    method: RequestHttpEnum.GET,
    params
  })
}

export const post = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
  return axiosInstance<T>({
    url,
    method: RequestHttpEnum.POST,
    data,
    headers: {
      'Content-Type': headersType || ContentTypeEnum.JSON
    }
  })
}

export const patch = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
  return axiosInstance<T>({
    url,
    method: RequestHttpEnum.PATCH,
    data,
    headers: {
      'Content-Type': headersType || ContentTypeEnum.JSON
    }
  })
}

export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
  return axiosInstance<T>({
    url,
    method: RequestHttpEnum.PUT,
    data,
    headers: {
      'Content-Type': headersType || ContentTypeEnum.JSON
    }
  })
}

export const del = <T = any>(url: string, params?: object) => {
  return axiosInstance<T>({
    url,
    method: RequestHttpEnum.DELETE,
    params
  })
}

export const http = (type?: RequestHttpEnum) => {
  switch (type) {
    case RequestHttpEnum.GET:
      return get
    case RequestHttpEnum.POST:
      return post
    case RequestHttpEnum.PATCH:
      return patch
    case RequestHttpEnum.PUT:
      return put
    case RequestHttpEnum.DELETE:
      return del
    default:
      return get
  }
}

const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | Record<any, any>) => {
  if (typeof target === 'string') {
    if (target.startsWith(prefix)) {
      const funStr = target.split(prefix)[1]
      let result
      try {
        result = new Function(`${funStr}`)()
      } catch (error) {
        console.log(error)
        window.$message.error('js内容解析有误!')
      }
      return result
    } else {
      return target
    }
  }
  for (const key in target) {
    if (Object.prototype.hasOwnProperty.call(target, key)) {
      const subTarget = target[key]
      target[key] = translateStr(subTarget)
    }
  }
}

// 自定义请求
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
  if (!targetParams || !globalParams) {
    return
  }
  // 全局
  const {
    // 全局请求源地址
    requestOriginUrl,
    // 全局请求内容
    requestParams: globalRequestParams
  } = globalParams

  // 目标组件（优先级 > 全局组件）
  const {
    // 请求地址
    requestUrl,
    // 请求类型，普通 / sql
    requestContentType,
    // 获取数据的方式
    requestDataType,
    // 请求方式
    requestHttpType,
    // 请求类型
    requestParamsBodyType,
    // SQL请求对象
    requestSQLContent,
    // 请求内容
    requestParams: targetRequestParams
  } = targetParams

  // 静态数据排除
  if (requestDataType === RequestDataTypeEnum.STATIC) return

  if (!requestUrl) {
    return
  }

  // 处理头部
  let headers: RequestParamsObjType = {
    ...globalRequestParams[RequestParamsTypeEnum.HEADER],
    ...targetRequestParams[RequestParamsTypeEnum.HEADER]
  }
  headers = translateStr(headers)

  // data参数
  let data: RequestParamsObjType | FormData | string = {}
  // params参数
  let params: RequestParamsObjType = { ...targetRequestParams.Params }
  params = translateStr(params)
  // form 类型处理
  let formData: FormData = new FormData()

  // 类型处理
  switch (requestParamsBodyType) {
    case RequestBodyEnum.NONE:
      break
    case RequestBodyEnum.JSON:
      headers['Content-Type'] = ContentTypeEnum.JSON
      // json对象也能使用'javascript：'来动态拼接参数
      data = translateStr(targetRequestParams.Body[RequestBodyEnum.JSON])
      if (typeof data === 'string') data = JSON.parse(data)
      break
    case RequestBodyEnum.XML:
      headers['Content-Type'] = ContentTypeEnum.XML
      // xml字符串赋值给data
      data = translateStr(targetRequestParams.Body[RequestBodyEnum.XML])
      break
    case RequestBodyEnum.X_WWW_FORM_URLENCODED:
      headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
      const bodyFormData = targetRequestParams.Body[RequestBodyEnum.X_WWW_FORM_URLENCODED]
      for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
      // FormData 赋值给 data
      data = formData
      break
    case RequestBodyEnum.FORM_DATA:
      headers['Content-Type'] = ContentTypeEnum.FORM_DATA
      const bodyFormUrlencoded = targetRequestParams.Body[RequestBodyEnum.FORM_DATA]
      for (const i in bodyFormUrlencoded) formData.set(i, translateStr(bodyFormUrlencoded[i]))
      // FormData 赋值给 data
      data = formData
      break
  }

  // sql处理
  if (requestContentType === RequestContentTypeEnum.SQL) {
    headers['Content-Type'] = ContentTypeEnum.JSON
    data = requestSQLContent
  }

  try {
    const url = new Function('return `' + `${requestOriginUrl}${requestUrl}`.trim() + '`')()
    return axiosInstance({
      url,
      method: requestHttpType,
      data,
      params,
      headers
    })
  } catch (error) {
    console.log(error)
    window.$message.error('URL地址错误有误!')
  }
}
